Categories
React

react-overlays — Tooltips

Spread the love

Tooltips are something that we have to add often into our React app.

To make this task easier, we can use existing component libraries to add them.

In this article, we’ll look at how to add tooltips into our React app with the react-overlays library.

Ovelays

We can add overlays easily with the Overlay component.

To add it, we can write:

import React, { useReducer, useRef, useState } from "react";
import styled from "styled-components";
import Overlay from "react-overlays/Overlay";

const Tooltip = styled("div")`
  position: absolute;
`;

const Arrow = styled("div")`
  position: absolute;
  width: 10px;
  height: 10px;
  z-index: -1;

  &::before {
    content: "";
    position: absolute;
    transform: rotate(45deg);
    background: #000;
    width: 10px;
    height: 10px;
    top: 0;
    left: 0;
  }

  ${(p) =>
    ({
      left: "right: -4px;",
      right: "left: -4px;",
      top: "bottom: -4px;",
      bottom: "top: -4px;"
    }[p.placement])}
`;

const Body = styled("div")`
  padding: 3px 8px;
  color: #fff;
  text-align: center;
  border-radius: 3px;
  background-color: #000;
`;

const PLACEMENTS = ["left", "top", "right", "bottom"];

const initialSstate = {
  show: false,
  placement: null
};

function reducer(state, [type, payload]) {
  switch (type) {
    case "placement":
      return { show: !!payload, placement: payload };
    case "hide":
      return { ...state, show: false, placement: null };
    default:
      return state;
  }
}

export default function App() {
  const [{ show, placement }, dispatch] = useReducer(reducer, initialSstate);
  const triggerRef = useRef(null);
  const containerRef = useRef(null);

  const handleClick = () => {
    const nextPlacement = PLACEMENTS[PLACEMENTS.indexOf(placement) + 1];

dispatch(["placement", nextPlacement]);
  };

  return (
    <div className="flex flex-col items-center" ref={containerRef}>
      <button
        type="button"
        className="btn mb-4"
        id="overlay-toggle"
        ref={triggerRef}
        onClick={handleClick}
        style={{ marginTop: 200, marginLeft: 200 }}
      >
        I am an Overlay target
      </button>
      <Overlay
        show={show}
        rootClose
        offset={[0, 10]}
        onHide={() => dispatch("hide")}
        placement={placement}
        container={containerRef}
        target={triggerRef}
      >
        {({ props, arrowProps, placement }) => (
          <Tooltip {...props} placement={placement}>
            <Arrow
              {...arrowProps}
              placement={placement}
              style={arrowProps.style}
            />
            <Body>
              <strong>{placement}</strong>
            </Body>
          </Tooltip>
        )}
      </Overlay>
    </div>
  );
}

We create the Tooltip component to add the tooltip container.

Then we add the Arrow component to add the arrow for the tooltip.

The Arrow is the child of Tooltip so that it’s attached to the tooltip.

The Body component is a div that has the content of the tooltip.

We can set the placement state to set the placement of the tooltip.

Its value is passed into the placement prop to set the placement.

The possible values are 'left' , 'top' , 'right' , and 'bottom' .

The Overlay component takes a few props to let us adjust it.

The show prop controls when the overlay is shown.

rootClose lets us close the tooltip when we click outside of it.

offset has the horizontal and vertical offsets.

placement has the placement of the tooltip.

containerRef has the container component for the tooltip.

target has the ref for the component to trigger the tooltip.

Now when we click on the button, we see the tooltip show at different locations each time as we change the placement each time.

Conclusion

We can add tooltips into our React app with the Overlays component provided by the React Overlays library.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *